package com.example.performance.service;

import com.example.performance.engine.LoadTestEngine;
import com.example.performance.model.LoadTestConfig;
import com.example.performance.model.TestReport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * 测试执行服务
 * 负责管理和执行性能测试任务
 */
@Service
public class TestExecutionService {

    private static final Logger logger = LoggerFactory.getLogger(TestExecutionService.class);

    private final Map<String, TestSession> activeSessions = new ConcurrentHashMap<String, TestSession>();
    private final Executor executor = Executors.newCachedThreadPool(r -> {
        Thread thread = new Thread(r);
        thread.setName("TestExecution-" + thread.getId());
        thread.setDaemon(true);
        return thread;
    });

    /**
     * 启动测试会话
     * 
     * @param sessionId 会话ID
     * @param config    测试配置
     * @return 测试会话对象
     */
    public TestSession startTest(String sessionId, LoadTestConfig config) {
        if (activeSessions.containsKey(sessionId)) {
            throw new IllegalArgumentException("测试会话已存在: " + sessionId);
        }

        TestSession session = new TestSession(sessionId, config);
        activeSessions.put(sessionId, session);

        // 异步执行测试
        CompletableFuture.runAsync(() -> executeTest(session), executor);

        logger.info("启动测试会话: {}, 配置: {}", sessionId, config.getTestName());
        return session;
    }

    /**
     * 停止测试会话
     * 
     * @param sessionId 会话ID
     */
    public boolean stopTest(String sessionId) {
        TestSession session = activeSessions.get(sessionId);
        if (session != null) {
            session.stop();
            logger.info("停止测试会话: {}", sessionId);
            return true;
        }
        return false;
    }

    /**
     * 获取测试会话
     * 
     * @param sessionId 会话ID
     * @return 测试会话对象
     */
    public TestSession getTestSession(String sessionId) {
        return activeSessions.get(sessionId);
    }

    /**
     * 获取所有活跃的测试会话
     * 
     * @return 活跃会话Map
     */
    public Map<String, TestSession> getAllActiveSessions() {
        return new ConcurrentHashMap<String, TestSession>(activeSessions);
    }

    /**
     * 清理已完成的测试会话
     */
    public void cleanupCompletedSessions() {
        activeSessions.entrySet().removeIf(entry -> {
            TestSession session = entry.getValue();
            return session.getStatus() == TestStatus.COMPLETED ||
                    session.getStatus() == TestStatus.FAILED ||
                    session.getStatus() == TestStatus.STOPPED;
        });
    }

    /**
     * 执行测试
     */
    private void executeTest(TestSession session) {
        LoadTestEngine engine = new LoadTestEngine();

        try {
            session.setStatus(TestStatus.RUNNING);
            session.setStartTime(System.currentTimeMillis());

            // 执行负载测试
            TestReport report = engine.executeLoadTest(session.getConfig());

            session.setReport(report);
            session.setStatus(TestStatus.COMPLETED);
            session.setEndTime(System.currentTimeMillis());

            logger.info("测试会话完成: {}", session.getSessionId());

        } catch (Exception e) {
            logger.error("测试执行失败: {}", session.getSessionId(), e);
            session.setStatus(TestStatus.FAILED);
            session.setErrorMessage(e.getMessage());
            session.setEndTime(System.currentTimeMillis());
        } finally {
            engine.shutdown();
        }
    }

    /**
     * 测试会话状态枚举
     */
    public enum TestStatus {
        PREPARING("准备中"),
        RUNNING("运行中"),
        COMPLETED("已完成"),
        STOPPED("已停止"),
        FAILED("执行失败");

        private final String description;

        TestStatus(String description) {
            this.description = description;
        }

        public String getDescription() {
            return description;
        }
    }

    /**
     * 测试会话类
     */
    public static class TestSession {
        private final String sessionId;
        private final LoadTestConfig config;
        private TestStatus status;
        private long startTime;
        private long endTime;
        private TestReport report;
        private String errorMessage;
        private volatile boolean stopRequested;

        public TestSession(String sessionId, LoadTestConfig config) {
            this.sessionId = sessionId;
            this.config = config;
            this.status = TestStatus.PREPARING;
            this.stopRequested = false;
        }

        public void stop() {
            this.stopRequested = true;
            this.status = TestStatus.STOPPED;
        }

        // Getter和Setter方法
        public String getSessionId() {
            return sessionId;
        }

        public LoadTestConfig getConfig() {
            return config;
        }

        public TestStatus getStatus() {
            return status;
        }

        public void setStatus(TestStatus status) {
            this.status = status;
        }

        public long getStartTime() {
            return startTime;
        }

        public void setStartTime(long startTime) {
            this.startTime = startTime;
        }

        public long getEndTime() {
            return endTime;
        }

        public void setEndTime(long endTime) {
            this.endTime = endTime;
        }

        public TestReport getReport() {
            return report;
        }

        public void setReport(TestReport report) {
            this.report = report;
        }

        public String getErrorMessage() {
            return errorMessage;
        }

        public void setErrorMessage(String errorMessage) {
            this.errorMessage = errorMessage;
        }

        public boolean isStopRequested() {
            return stopRequested;
        }

        /**
         * 获取测试进度（百分比）
         */
        public double getProgress() {
            if (status == TestStatus.COMPLETED || status == TestStatus.STOPPED) {
                return 100.0;
            }

            if (status != TestStatus.RUNNING || startTime == 0) {
                return 0.0;
            }

            long elapsed = System.currentTimeMillis() - startTime;
            long totalDuration = config.getTestDurationSeconds() * 1000L;

            return Math.min(100.0, (double) elapsed / totalDuration * 100);
        }

        /**
         * 获取运行时间（毫秒）
         */
        public long getElapsedTime() {
            if (startTime == 0)
                return 0;

            if (endTime > 0) {
                return endTime - startTime;
            } else {
                return System.currentTimeMillis() - startTime;
            }
        }
    }
}